/**
 ******************************************************************************
 * @file         dBle_slave.c
 * @brief        Ble 设备底层驱动程序
 * @author       Leo
 * @date         2022-3-9
 * @version      v001
 * @copyright    dxtc
 *
 * @note         鼎新同创·智能锁
 *
 ******************************************************************************
 */

#include "device.h"
#include "component.h"

//昂瑞微的驱动库API
#include "rwip.h" // RW SW initialization
#include "co_debug.h"
#include "app.h"
#include "peripheral.h"
#include "cfg.h"
#include "app_lkm3_server.h"
#include "debug_config.h"
#include "app_task.h" // Application task definitions

//#define BLE_ADV_NAME ("arlf_SE60") //D288X HK01
//#define BLE_ADV_NAME_LEN (sizeof(BLE_ADV_NAME) - 1)
#define BLE_ADV_NAME_TYPE_SHORT (0X08)
#define BLE_ADV_NAME_TYPE_COMPLETE (0X09)

/* BLE协议中，广播包中的ADtype */
#define ADV_TYPE_FLAGS          0x01        //蓝牙特性,General discover mode
#define ADV_TYPE_SERVICE_UUID   0x02        //服务的UUID 0x02~0x07
#define ADV_TYPE_LOCAL_NAME     0x09        //蓝牙名称   0x08/0x09
#define ADV_TYPE_TX_POWER       0x0A        //发射功率
#define ADV_TYPE_SERVICE_DATA   0x16        //服务数据
#define ADV_TYPE_MANUFACTURER   0XFF        //厂商信息

//#define TEST_ESN "SE60XC124100002"// "D288XC123C00001" 
#define LOCK_MODE "LON01" //LON23项目 
//#define PROJECT_DEFAULT_BLE_ADDR {0xFC, 0x61, 0x79, 0xCE, 0x98, 0x33 }
static uint8_t bleMacAddr[6] = {0};
static BleAdv_stu_t  adv_buff;                      // 用于存储广播信息

#pragma pack(1)
typedef struct
{
    uint8_t nameLen;
    uint8_t nameType;
    uint8_t nameData[];
} Ble_advName_config_stu_t;

typedef struct 
{
    //HK01未绑定: 0xff 0xff 0x01  0x00  0x00  0x00 0x07      
    uint16_t Manufacturer_info; //通用厂商信息，固定为 0xff, 0xff 
    uint8_t Lndu_id;            //凌度内置的厂商ID, 一般为01
    uint8_t bind_flag;          //设备绑定标识  0x00: 未绑定  0x01:已绑定 
    uint8_t reserve;            //保留位,默认为0
    uint16_t product_id;        //HK01:0x0007
}AdvData_stu_t;

typedef struct
{
    uint8_t length;
    uint8_t advType;
    AdvData_stu_t data;
}Ble_ManufacturerType_stu_t;

typedef struct
{
    uint8_t length;
    uint8_t advType;
    uint8_t advData[16];//arlffc6179ce9833
}Ble_localNameType_stu_t;

typedef struct
{
    uint8_t length;
    uint8_t advType;
    uint8_t advData[9];
}Ble_MacType_stu_t;

typedef struct
{
    uint8_t length;
    uint8_t advType;
    uint8_t advData[2];
}Ble_ServiceUuidType_stu_t;
#pragma pack()


/**
 * @brief HEX转换为大写字符串
 * 
 * @param [in] hex hex数组指针
 * @param [in] hexLen hex数组长度
 * @param [in] str 字符串指针
 * 
 * @note 0x12345678  --> '12345678'
 */
static void hex_to_string(uint8_t *hex, uint8_t hexLen, uint8_t *str)
{
   uint8_t i = 0;

   for(i = 0; i < hexLen; i++)
	{
		snprintf((char *)str + i*2, 2+1, "%02x", hex[i]);
	}

   for (i = 0; i < hexLen*2; i++)
	{
      if(str[i] >= 'a' && str[i] <= 'z')
      {
         str[i] = str[i] - 0x20;
      }
	}
}

/**
 * @brief 设置蓝牙地址
 *
 * @param [out] adVaddr
 *
 * @note
 */
static void Ble_set_advAddr(uint8_t *adVaddr)
{
    bd_addr_t bleAddr;
    uint8_t bleAddrTemp[6];
    nvds_tag_len_t addr_len = 6;
    uint8_t uid_buf[16] = {0};
    uint8_t uid_buf_str[32] = {0};
    uint8_t uid_buf_MD5[16] = {0};

    memset(&bleAddr, 0xff, sizeof(bleAddr));
    memset(&bleAddrTemp, 0xff, sizeof(bleAddrTemp));

    /* 如果没有写入生产参数，那么自己先设置参数写入 */
    if (nvds_get(NVDS_TAG_BD_ADDRESS, &addr_len, bleAddr.addr) != NVDS_OK)
    {
        //< 产生随机数
        // uint32_t rand_data = HS_RANDOM->RANDOM;
        // uint32_t random = pmu_random_seed_fetch(rand_data);
        // //< MAC低3字节用随机数
        // memcpy(bleAddr.addr, &random, 3);

        //< MAC高3字节用0XA1A2A3（这里随便填的，等产品经理买到ID再改）
        // bleAddr.addr[0] = 0x00;
        // bleAddr.addr[1] = 0x00;
        // bleAddr.addr[2] = 0x00;

        // bleAddr.addr[3] = 0x98;
        // bleAddr.addr[4] = 0x2E;
        // bleAddr.addr[5] = 0x01;

        // bleAddr.addr[0] = 0x33;//0x2A
        // bleAddr.addr[1] = 0x98;
        // bleAddr.addr[2] = 0xCE;

        // bleAddr.addr[3] = 0x79;
        // bleAddr.addr[4] = 0x61;
        // bleAddr.addr[5] = 0xFC;  
#ifndef PROJECT_DEFAULT_BLE_ADDR
        sfs_read_uid_ex(uid_buf,sizeof(uid_buf));
        BLE_LOG_HEX("\n uid_buf", uid_buf, sizeof(uid_buf));

        hex_to_string(uid_buf, sizeof(uid_buf), uid_buf_str);
        BLE_LOG_D("uid_buf_str:%.*s ", sizeof(uid_buf_str),uid_buf_str);

        MD5_Calc(uid_buf_str, sizeof(uid_buf_str), uid_buf_MD5);
        BLE_LOG_HEX("uid_buf_MD5", uid_buf_MD5, sizeof(uid_buf_MD5));

        memcpy(&bleAddr.addr[0], uid_buf_MD5, sizeof(bleAddr.addr));
#else
        uint8_t bleDefaultAddr[6] = PROJECT_DEFAULT_BLE_ADDR;

        memcpy(&bleAddr.addr[0], bleDefaultAddr, sizeof(bleAddr.addr));
#endif
        //BLE_LOG_I("random:0x%x, addrlen:%d\r\n", random, addr_len);
        BLE_LOG_I("ble mac:%x,%x,%x,%x,%x,%x", bleAddr.addr[0], bleAddr.addr[1], bleAddr.addr[2], bleAddr.addr[3], bleAddr.addr[4], bleAddr.addr[5]);

        if (NVDS_OK == nvds_put(NVDS_TAG_BD_ADDRESS, addr_len, bleAddr.addr))
        {
            BLE_LOG_I("addr set success");
        }
    }

    /* 蓝牙地址实际是反序显示的 */
    for (uint8_t i = 0; i < 6; i++)
    {
        bleAddrTemp[i] = bleAddr.addr[5 - i];
    }
    log_info_array_ex("ble addr data", bleAddrTemp, addr_len);

    memcpy(adVaddr, bleAddrTemp, sizeof(bleAddrTemp));
    memcpy(bleMacAddr, bleAddrTemp, sizeof(bleAddrTemp));
}
/**
 * @brief 初始化蓝牙地址和广播参数
 *
 *
 * @note
 */
void Ble_hardware_Init(uint8_t bindflag)
{
    Ble_advName_config_stu_t *pAdvName = NULL;
    uint8_t adv_len = 0;
    uint8_t flag = 0;

    flag = bindflag;
//    uint8_t bleAddr[6] = {0};

    //Ble_set_advAddr(bleAddr);
    /* 设置蓝牙广播包参数  蓝牙完整名称 */
    //uint8_t default_adv_data[ADV_DATA_LEN - 3];
    //uint16_t adv_len = 0;

    //pAdvName = (Ble_advName_config_stu_t *)default_adv_data;
    //pAdvName->nameType = BLE_ADV_NAME_TYPE_COMPLETE;
    //pAdvName->nameLen = BLE_ADV_NAME_LEN + 1;
    //memcpy(pAdvName->nameData, BLE_ADV_NAME, BLE_ADV_NAME_LEN);

    //adv_len = sizeof(Ble_advName_config_stu_t) + BLE_ADV_NAME_LEN;
    // log_info_array_ex("adv data", default_adv_data, adv_len);
    //appm_adv_set_adv_data((uint8_t *)default_adv_data, adv_len);

    /* 设置蓝牙扫描回应包参数  公司ID(2字节默认为0) + MAC地址 */
    //uint8_t res_data[10] = {0x09, 0xFF, 0x00, 0x00};
    //uint8_t res_data_len = sizeof(res_data);

    //memcpy(&res_data[4], bleAddr, sizeof(bleAddr));
    //appm_adv_set_res_data(res_data, res_data_len);

    //设置蓝牙广播包参数和蓝牙扫描回应包参数
    Ble_ManufacturerType_stu_t *ManufacturerInfo = NULL;
    Ble_localNameType_stu_t *localName = NULL;
    Ble_MacType_stu_t *blemac = NULL;
    Ble_ServiceUuidType_stu_t *serviceUUID = NULL;
    uint16_t custom_service_uuid[] = {0xA201};
    //uint8_t mac_test[9] = {0x01, 0xA2, 0x00, 0xfc, 0x61, 0x79, 0xce, 0x98, 0x33};//0x00:未绑定 0x01:已绑定;  MAC从 bleAddr 获取


    BleAdv_stu_t advParam;
    memset(&advParam.adv[0], 0x00, sizeof(BleAdv_stu_t));
    ManufacturerInfo = (Ble_ManufacturerType_stu_t *)&advParam.adv[0];
    ManufacturerInfo->length = 0x08;
    ManufacturerInfo->advType = ADV_TYPE_MANUFACTURER;
    ManufacturerInfo->data.Manufacturer_info = 0xffff; 
    ManufacturerInfo->data.Lndu_id = 0x01;
    //绑定标志位
    if (flag == 1)
    {
        BLE_LOG_D("data.bind_flag:1");
        ManufacturerInfo->data.bind_flag = 0x01;
    }
    else if (flag == 0)
    {
        BLE_LOG_D("data.bind_flag:0");
        ManufacturerInfo->data.bind_flag = 0x00;
    }
    else
    {
        BLE_LOG_D(">>>>data.bind_flag:0");
        ManufacturerInfo->data.bind_flag = 0x00;
    }

    ManufacturerInfo->data.reserve = 0x00;
    ManufacturerInfo->data.product_id = 0x0700;
    advParam.adv_len = sizeof(Ble_ManufacturerType_stu_t);

    localName = (Ble_localNameType_stu_t *)&advParam.scan[0];
    localName->length = 0x11;
    localName->advType = ADV_TYPE_LOCAL_NAME;
    sprintf((char *)&localName->advData[0], "arlf%02x%02x%02x%02x%02x%02x", bleMacAddr[0], bleMacAddr[1],
            bleMacAddr[2], bleMacAddr[3], bleMacAddr[4], bleMacAddr[5]);

    serviceUUID = (Ble_ServiceUuidType_stu_t *)++localName;
    serviceUUID->length = 0x03;
    serviceUUID->advType = ADV_TYPE_SERVICE_UUID;//
    memcpy(serviceUUID->advData, custom_service_uuid, sizeof(custom_service_uuid));
    advParam.scan_len = sizeof(Ble_localNameType_stu_t) + sizeof(Ble_ServiceUuidType_stu_t);

    // blemac = (Ble_MacType_stu_t *)++serviceUUID;
    // blemac->length = 0x0A;
    // blemac->advType = 0x16;//
    // memcpy(blemac->advData, mac_test, sizeof(mac_test));
    // advParam.scan_len = sizeof(Ble_localNameType_stu_t) + sizeof(Ble_ServiceUuidType_stu_t)+ sizeof(Ble_MacType_stu_t);

	appm_adv_set_adv_data((uint8_t *)advParam.adv, advParam.adv_len);
	appm_adv_set_res_data((uint8_t *)advParam.scan, advParam.scan_len);

    /* 防止没有及时刷新，设置参数完成后调度一下 */
    OSAL_LoopHook();
}

/**
 * @brief 接收蓝牙下发的数据
 *
 * @param [in] buff
 * @param [in] len
 *
 * @note
 */
#if (BLE_APP_LKM3_SERVER)
void app_lkm3_server_recv_data(uint8_t *buff, uint16_t len)
#elif (BLETOAPP_SERVER)
void app_bleapp_server_recv_data(uint8_t *buff, uint16_t len)
#elif (BLE_APP_HK01_SERVER)
void app_hk01_server_recv_data(uint8_t *buff, uint16_t len)
#endif
{
    //BLE_LOG_HEX("Dble recv data:", buff, len);//
    Device_IRQHandler(vBLE_0, (void *)buff, (PUBLISH_APP_CMD << 16) | len);
}
/**
 * @brief  Ble连接成功回调
 * @note
 */
void app_gap_connected_handler(ke_msg_id_t const msgid,
                               struct gapc_connection_req_ind const *param,
                               ke_task_id_t const dest_id,
                               ke_task_id_t const src_id)
{
    BLE_LOG_I("Connecting to moble");
    uint8_t status = 1;
    Device_IRQHandler(vBLE_0, &status, (PUBLISH_BLE_STATUS << 16) | 1);
}

void app_gap_disconnected_handler(ke_msg_id_t const msgid,
                                  struct gapc_disconnect_ind const *param,
                                  ke_task_id_t const dest_id,
                                  ke_task_id_t const src_id)
{
    BLE_LOG_I("Disconnect to moble");
    uint8_t status = 0;
    Device_IRQHandler(vBLE_0, &status, (PUBLISH_BLE_STATUS << 16) | 1);
}

/**
 * @brief  处理dongle MAC和GATT数据，开始校准
 * @note
 *
 * @param
 */
static int32_t Ble_ReadDongleParam(uint8_t *data, uint16_t len)
{
#if CONFIG_FREQ_CALIB_ENABLE
#define ONMICRO_DONGLE_MAC_LEN 7

#define ONMICRO_DONGLE_GATT_LEN 2

    if (len != ONMICRO_DONGLE_MAC_LEN + ONMICRO_DONGLE_GATT_LEN)
    {
        BLE_LOG_W("read dongle error, len = %d", len);
        return -1;
    }
    // dangle mac
    //BLE_LOG_HEX("dangle mac =", 16, data, ONMICRO_DONGLE_MAC_LEN);
		BLE_LOG_HEX("dangle mac =", data, 16);
    // dangle gatt
    app_env.freq_peer_handle = data[ONMICRO_DONGLE_MAC_LEN + 1] << 8 | data[ONMICRO_DONGLE_MAC_LEN];  // 低字节在前
    BLE_LOG_D("dangle gatt = 0x%04x", app_env.freq_peer_handle);
    /* 开始校准标志位 */
    app_env.freq_calib_start = 1;
    // appm_adv_start();//通过ate上层打开蓝牙广播，此处不打开
#endif
    return 0;
}

/**
 * @brief 更新蓝牙广播参数
 * 
 * @param [in] data 
 * 
 * @note 
 */
static void Ble_updata_Adv_param(BleAdv_stu_t *data)
{
    extern void appm_advertising_init(void);

    appm_adv_stop(1);
    memcpy(&adv_buff, data, sizeof(BleAdv_stu_t));
    appm_advertising_init();

    //Ble_hardware_Init(); 
    appm_adv_set_adv_data(adv_buff.adv, adv_buff.adv_len);
    appm_adv_set_res_data(adv_buff.scan, adv_buff.scan_len);

    BLE_LOG_D("Ble updata Adv param");	
    appm_adv_start();

    /* 防止没有及时刷新，设置参数完成后调度一下 */
    OSAL_LoopHook();
}

/**
 * @brief  Ble驱动，write接口
 * @note
 * @param  pCmd：命令
 *         param：参数---还需根据param来添加特征值处理
 *
 * @return SUCCESS   ERROR
 */
static int32_t dBle_Write(VirtualHardware_enum_t dev, void *data, uint32_t len, uint32_t param)
{
    if (param == BLE_CTRL_SET_BINDFLAG)//设置绑定标志
    {
        uint8_t *flag = data;

        BLE_LOG_D("*flag:%d", *flag);
    #if 1
        appm_adv_stop(1);
        //memcpy(&adv_buff, data, sizeof(BleAdv_stu_t));
        appm_advertising_init();

        Ble_hardware_Init(*flag);
        // appm_adv_set_adv_data(adv_buff.adv, adv_buff.adv_len);
        // appm_adv_set_res_data(adv_buff.scan, adv_buff.scan_len);
    #endif

    #if 0
		void appm_advertising_update(void);
        appm_adv_update_state(false);
        appm_advertising_update();
    #endif
    
        BLE_LOG_D("Ble updata Adv param");	
        appm_adv_start();
    } 
    else if (param == BLE_CTRL_DATA)
    {
        if (dev == vBLE_0)
        {
            //BLE_LOG_HEX("Dble send:", data, len);
            #if (BLE_APP_LKM3_SERVER)
                app_lkm3_server_send_data(data, len);
            #elif (BLETOAPP_SERVER)
                app_bleapp_server_send_data(data, len);
            #elif (BLE_APP_HK01_SERVER)
                app_hk01_server_send_data(data, len);
            #endif
        }
    }
    else if (param == BLE_CTRL_DISCONNECT)
    {
        if (dev == vBLE_0)
        {
            ke_state_t state = ke_state_get(TASK_APP);
            if (state == APPM_CONNECTED)
            {
                appm_disconnect(0); //主动断开蓝牙
                BLE_LOG_I("BLE_CTRL_APP_TASK_DISCONNECT");
            }
        }
    }

    else if (param == BLE_CTRL_CALIBRATION)
    {
        if (dev == vBLE_0)
        {
            Ble_ReadDongleParam(data, len);
        }
    }

    else if (param == BLE_CTRL_SET_MAC) //设置广播地址
    {
        if (dev == vBLE_0)
        {
            bd_addr_t addr;
            uint8_t *p = data;
            for (size_t i = 0; i < 6; i++)
            {
                addr.addr[i] = p[5 - i];
            }
            appm_adv_stop(1);
            nvds_put(NVDS_TAG_BD_ADDRESS, 6, &addr);
        }
    }
    return 0;
}

/**
 * @brief  Ble驱动，write接口
 * @note
 * @param  pCmd：命令
 *         param：参数---还需根据param来添加特征值处理
 *
 * @return SUCCESS   ERROR
 */
static int32_t dBle_Read(VirtualHardware_enum_t dev, void *data, uint32_t len, uint32_t param)
{
    if (dev == vBLE_0)
    {
        uint8_t buff[10] = { 0 };
        switch (param)
        {      
#if CONFIG_FREQ_CALIB_ENABLE
            case PUBLISH_CALIBRATION_FREQ:
                buff[0] = app_env.freq_local_handle & 0xff;
                buff[1] = (app_env.freq_local_handle >> 8) & 0xff;
                buff[2] = app_env.xtal32m_ctune;
                memcpy(data, buff, len);
                BLE_LOG_D("get gatt: 0x%04x , xtal32m:%d", app_env.freq_local_handle, app_env.xtal32m_ctune);
                break;
#endif
            default:
                BLE_LOG_W("Ble Read param is invalid, %d", param);
                break;
        }
    }
    return 0;
}

/**
 * @brief  BLE驱动 Enable接口
 *
 * @note   开启（初始化）设备（唤醒）
 */
static int8_t dBle_Enable(VirtualHardware_enum_t dev)
{
    static FlagStatus power_on = RESET;
    uint8_t bleAddr[6] = {0};
    if (power_on == RESET)
    {
        power_on = SET;
        BLE_LOG_I("Ble HWL Init\r\n");
        Ble_set_advAddr(bleAddr);
        Ble_hardware_Init(0);//TODO:绑定标志位的广播处理
        //< 发给组件层协议栈启动成功
        Device_IRQHandler(vBLE_0, bleMacAddr, (PUBLISH_BLE_MAC << 16) | sizeof(bleMacAddr));
    }
    appm_adv_start();
    return 0;
}
/**
 * @brief  BLE驱动 Disable 接口
 *
 * @note   休眠前断开连接
 */
static int8_t dBle_Disable(VirtualHardware_enum_t dev)
{
    return 0;
}

/**
 * @brief  Ble设备，init接口
 *
 * @note
 */
static void dBle_Init(void)
{
    // BLE_LOG_I("Ble HWL Init\r\n");
    // Ble_hardware_Init();

    /* 将底层设备具体操作接口，挂到设备控制块里面 */
    Device_stu_t *dcb = Device_GetDeviceCtrlBlock(vBLE);
    dcb->enable = dBle_Enable;
    dcb->disable = dBle_Disable;
    dcb->write = dBle_Write;
    dcb->read = dBle_Read;
}
INIT_PREV_EXPORT(dBle_Init);
